﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SuperX.Common.Helper
{
    public static class BinaryExtenstion
    {
        /// <summary>
        /// 在缓存内移动有效数据
        /// </summary>
        /// <param name="buffer">缓存</param>
        /// <param name="currentOffset">有效数据开始下标</param>
        /// <param name="length">有效数据长度</param>
        /// <param name="destOffset">移动的目标下标</param>
        /// <returns>负数：向左移动；0：不移动；正数：向右移动</returns>
        public static int Move(this byte[] buffer, int currentOffset, int length, int destOffset)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return 0;
            }
            if (currentOffset < 0 || currentOffset > buffer.Length - 1)
            {
                throw new IndexOutOfRangeException("currentOffset超出数组范围");
            }
            if (length == 0)
            {
                return 0;
            }
            if (destOffset < 0 || destOffset > buffer.Length - 1)
            {
                throw new IndexOutOfRangeException("destOffset超出数组范围");
            }
            int num = length + currentOffset - 1;
            if (destOffset >= currentOffset && destOffset <= num)
            {
                throw new ArgumentOutOfRangeException("destOffset不在有效的范围内");
            }
            int num2 = 0;
            if (destOffset < currentOffset)
            {
                num2 = destOffset - currentOffset;
                for (int i = currentOffset; i <= num; i++)
                {
                    buffer[i + num2] = buffer[i];
                }
            }
            else if (destOffset > num)
            {
                num2 = destOffset - num;
                for (int j = num; j >= currentOffset; j--)
                {
                    buffer[j + num2] = buffer[j];
                }
            }
            return num2;
        }

        /// <summary>
        /// 比对数据是事相等
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <param name="startIndex">要比较的buffer开始下标</param>
        /// <param name="markBytes">要比较的目标字节数组</param>
        public static bool Mark(this byte[] buffer, int offset, int length, int startIndex, byte[] markBytes)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return false;
            }
            if (offset < 0 || offset > buffer.Length - 1)
            {
                throw new IndexOutOfRangeException("offset超出数组范围");
            }
            if (length == 0)
            {
                return false;
            }
            int num = offset + length - markBytes.Length;
            if (startIndex < offset || startIndex > num)
            {
                throw new ArgumentOutOfRangeException("startIndex不在有效的范围内");
            }
            if (markBytes == null || markBytes.Length == 0)
            {
                throw new NullReferenceException("markBytes引用为空");
            }
            if (length < markBytes.Length)
            {
                return false;
            }
            bool flag = true;
            for (int i = 0; i < markBytes.Length; i++)
            {
                if (buffer[startIndex + i] != markBytes[i])
                {
                    flag = false;
                }
                if (!flag)
                {
                    break;
                }
            }
            return flag;
        }

        /// <summary>
        /// 获取标志位
        /// </summary>
        /// <param name="buffer">字节内容</param>
        /// <param name="offset">偏移位</param>
        /// <param name="length">长度</param>
        /// <param name="markBytes">标志位内容</param>
        /// <returns></returns>
        public static int Mark(this byte[] buffer, int offset, int length, byte[] markBytes)
        {
            int result = -1;
            int num = length - markBytes.Length;
            for (int i = offset; i < num; i++)
            {
                if (buffer.Mark(offset, length, i, markBytes))
                {
                    result = i;
                    break;
                }
            }
            return result;
        }
    }
}
